<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title></title>
</head>
<body>
<!-- 这里是样式 -->
</body>
</html>
<script>
// 这里是逻辑
//  用于描述对象的属性 控制它的行为  可写可以读 可以遍历等等
// 每个属性都有自己对应的属性描述对象，保存该属性的一些元信息。

// 属性描述对象提供6个元属性。



// {
//   value: 123,
//   writable: false,
//   enumerable: true,
//   configurable: false,
//   get: undefined,
//   set: undefined
// }
// 属性描述对象提供6个元属性。

// （1）value

// value是该属性的属性值，默认为undefined。

// （2）writable

// writable是一个布尔值，表示属性值（value）是否可改变（即是否可写），默认为true。

// （3）enumerable

// enumerable是一个布尔值，表示该属性是否可遍历，默认为true。如果设为false，会使得某些操作（比如for...in循环、Object.keys()）跳过该属性。

// （4）configurable

// configurable是一个布尔值，表示可配置性，默认为true。如果设为false，将阻止某些操作改写该属性，比如无法删除该属性，也不得改变该属性的属性描述对象（value属性除外）。也就是说，configurable属性控制了属性描述对象的可写性。

// （5）get

// get是一个函数，表示该属性的取值函数（getter），默认为undefined。

// （6）set

// set是一个函数，表示该属性的存值函数（setter），默认为undefined。

var obj = { p: 'a' };
// Object.getOwnPropertyDescriptor()方法获取obj.p的属性描述对
// Object.getOwnPropertyDescriptor()方法只能用于对象自身的属性，不能用于继承的属性。
Object.getOwnPropertyDescriptor(obj, 'p')
// Object { value: "a",
//   writable: true,//可以读写
//   enumerable: true,、、可以遍历
//   configurable: true// 可以配置的参数
// }
Object.getOwnPropertyNames()
// Object.getOwnPropertyNames方法返回一个数组，成员是参数对象自身的全部属性的属性名，不管该属性是否可遍历。

var obj = Object.defineProperties({}, {
  p1: { value: 1, enumerable: true },
  p2: { value: 2, enumerable: false }
});

Object.getOwnPropertyNames(obj)
// ["p1", "p2"]
var obj = Object.defineProperties({}, {
  p1: { value: 1, enumerable: true },
  p2: { value: 2, enumerable: false }
});

Object.getOwnPropertyNames(obj)
// ["p1", "p2"]
// 上面代码中，obj.p1是可遍历的，obj.p2是不可遍历的。Object.getOwnPropertyNames会将它们都返回。


// JavaScript 还提供了存取器的另一种写法。

// 写法二
var obj = {
  get p() {
    return 'getter';
  },
  set p(value) {
    console.log('setter: ' + value);
  }
};









</script>